#include "gtest/gtest.h"
#include "container/spw_deque.h"
#include <iostream>
#include <deque>
#include "container/spw_vector.h"
using namespace spwstd;

struct ElemTest {
    ElemTest(): a(new int(3))
    {
    }

    explicit ElemTest(int x): a(new int(x))
    {
    }

    ElemTest(const ElemTest& other) {
        a = new int(0);
        *a = *other.a;
    }
    ElemTest& operator= (const ElemTest& other) {
        a = new int(0);
        *a = *other.a;
        return *this;
    }

    ~ElemTest() {
        delete a; 
    }

public:
    int* a;
};

TEST(DequeTest, constructor) {
    // valgrand检测无内存泄漏
    Deque<ElemTest> d1(8, ElemTest());
    Deque<ElemTest> d2(64, ElemTest());
    {
        Deque<ElemTest> d3(65, ElemTest(1));
        EXPECT_EQ(*d3.Front().a, 1);
        EXPECT_EQ(*d3.Back().a, 1);
        EXPECT_EQ(d3.Size(), 65ul);
    }

    {
        Deque<ElemTest> d3(65, ElemTest(1));
        Deque<ElemTest> d4(spwuti::move(d3));
        EXPECT_EQ(*d4.Front().a, 1);
        EXPECT_EQ(*d4.Back().a, 1);
        EXPECT_EQ(d3.Size(), 0ul);
        EXPECT_EQ(d4.Size(), 65ul);
    }

    {
        Deque<ElemTest> d5{ElemTest(0), ElemTest(1), ElemTest(2)};
        EXPECT_EQ(*d5.Front().a, 0);
        EXPECT_EQ(*d5.Back().a, 2);
        EXPECT_EQ(d5.Size(), 3ul);
    }

    {
        spwstd::Vector<ElemTest> v{ElemTest(0), ElemTest(1), ElemTest(2)};
        Deque<ElemTest> d6(v.Begin(), v.End());
        EXPECT_EQ(*d6.Front().a, 0);
        EXPECT_EQ(*d6.Back().a, 2);
        EXPECT_EQ(d6.Size(), 3ul);
    }
}

TEST(DequeTest, capicity) {
    // size
    Deque<ElemTest> d2(11, ElemTest());
    EXPECT_EQ(d2.Size(), 11ul) << d2.Size();
}

TEST(DequeTest, modify) {
    // clear
    {
        Deque<ElemTest> d(11, ElemTest());
        EXPECT_EQ(d.Size(), 11ul) << d.Size();
        d.Clear();
        EXPECT_EQ(d.Size(), 0ul) << d.Size();
    }

    // push_back
    {
        Deque<int> p{1,2,3,4,5};
        p.PushBack(6);
        EXPECT_EQ(p.Size(), 6ul) << p.Size();
        EXPECT_EQ(p[0], 1) << p[0];
        EXPECT_EQ(p[5], 6) << p[5];
    }
    /*
    // erase
    {
        Deque<int> e{1,2,3,4,5};
        e.Erase(e.Begin()+3);
    }
    */
}